﻿using UniRx;
using System;

/// <summary>
/// 管理单位的所有数值属性
/// </summary>
public abstract class UnitAttributeBase : UnitComponentBase
{
    #region 基础属性

    /// <summary>
    /// 等级
    /// </summary>
    public int level { get => m_Level.Value; set => m_Level.Value = value; }
    public IObservable<int> onLevel => m_Level;
    private ReactiveProperty<int> m_Level = new ReactiveProperty<int>();

    /// <summary>
    /// 基础生命值
    /// </summary>
    public double baseHP { get => m_BaseHP.Value; set => m_BaseHP.Value = value; }
    public IObservable<double> onBaseHP => m_BaseHP;
    private ReactiveProperty<double> m_BaseHP = new ReactiveProperty<double>();

    /// <summary>
    /// 额外生命值
    /// </summary>
    public double extraHP { get => m_ExtraHP.Value; set => m_ExtraHP.Value = value; }
    public IObservable<double> onExtraHP => m_ExtraHP;
    private ReactiveProperty<double> m_ExtraHP = new ReactiveProperty<double>();

    /// <summary>
    /// 当前生命值
    /// </summary>
    public double currentHP { get => m_CurrentHP.Value; set => m_CurrentHP.Value = value; }
    public IObservable<double> onCurrentHP => m_CurrentHP;
    private ReactiveProperty<double> m_CurrentHP = new ReactiveProperty<double>();

    /// <summary>
    /// 总生命值
    /// </summary>
    public double totalHP => baseHP + extraHP;
    public IObservable<double> onTotalHP => Observable.Merge(onBaseHP, onExtraHP);

    /// <summary>
    /// 基础攻击力。只受角色本身影响，下同。
    /// </summary>
    public double baseAttack { get => m_BaseAttack.Value; set => m_BaseAttack.Value = value; }
    public IObservable<double> onBaseAttack => m_BaseAttack;
    private ReactiveProperty<double> m_BaseAttack = new ReactiveProperty<double>();

    /// <summary>
    /// 额外攻击力。各种装备、技能、药水等外在加成所获得的攻击力，下同。
    /// </summary>
    public double extraAttack { get => m_ExtraAttack.Value; set => m_ExtraAttack.Value = value; }
    public IObservable<double> onExtraAttack => m_ExtraAttack;
    private ReactiveProperty<double> m_ExtraAttack = new ReactiveProperty<double>();

    /// <summary>
    /// 总攻击力
    /// </summary>
    public double totalAttack => baseAttack + extraAttack;
    public IObservable<double> onTotalAttack => Observable.Merge(onBaseAttack, onExtraAttack);

    /// <summary>
    /// 基础防御力
    /// </summary>
    public double baseDefence { get => m_BaseDefence.Value; set => m_BaseDefence.Value = value; }
    public IObservable<double> onBaseDefence => m_BaseDefence;
    private ReactiveProperty<double> m_BaseDefence = new ReactiveProperty<double>();

    /// <summary>
    /// 额外防御力
    /// </summary>
    public double extraDefence { get => m_ExtraDefence.Value; set => m_ExtraDefence.Value = value; }
    public IObservable<double> onExtraDefence => m_ExtraDefence;
    private ReactiveProperty<double> m_ExtraDefence = new ReactiveProperty<double>();

    /// <summary>
    /// 总防御力。需要在计算时将固定的数值根据公式转换成减伤百分比
    /// </summary>
    public double totalDefence => baseDefence + extraDefence;
    public IObservable<double> onTotalDefence => Observable.Merge(onBaseDefence, onExtraDefence);

    /// <summary>
    /// 防御穿刺。在计算时，直接减少敌方对应数值的防御力
    /// </summary>
    public double defencePierce { get => m_DefencePierce.Value; set => m_DefencePierce.Value = value; }
    public IObservable<double> onDefencePierce => m_DefencePierce;
    private ReactiveProperty<double> m_DefencePierce = new ReactiveProperty<double>();

    /// <summary>
    /// 暴击率
    /// </summary>
    public double critical { get => m_Critical.Value; set => m_Critical.Value = value; }
    public IObservable<double> onCritical => m_Critical;
    private ReactiveProperty<double> m_Critical = new ReactiveProperty<double>();

    /// <summary>
    /// 暴击伤害
    /// </summary>
    public double criticalDamage { get => m_CriticalDamage.Value; set => m_CriticalDamage.Value = value; }
    public IObservable<double> onCriticalDamage => m_CriticalDamage;
    private ReactiveProperty<double> m_CriticalDamage = new ReactiveProperty<double>();

    /// <summary>
    /// 击退值。受到大于该值的伤害时产生僵直
    /// </summary>
    public double knockBack { get => m_KnockBack.Value; set => m_KnockBack.Value = value; }
    public IObservable<double> onKnockBack => m_KnockBack;
    private ReactiveProperty<double> m_KnockBack = new ReactiveProperty<double>();

    #endregion 基础属性

    #region 功能属性

    /// <summary>
    /// 移动速度
    /// </summary>
    public float speed { get => m_Speed.Value; set => m_Speed.Value = value; }
    public IObservable<float> onSpeed => m_Speed;
    private ReactiveProperty<float> m_Speed = new ReactiveProperty<float>();

    /// <summary>
    /// 跳跃力
    /// </summary>
    public float jumpAbility { get => m_JumpAbility.Value; set => m_JumpAbility.Value = value; }
    public IObservable<float> onJumpAbility => m_JumpAbility;
    private ReactiveProperty<float> m_JumpAbility = new ReactiveProperty<float>();

    /// <summary>
    /// 恢复力。每10秒恢复一次当前值数量的HP
    /// </summary>
    public double resilience { get => m_Resilience.Value; set => m_Resilience.Value = value; }
    public IObservable<double> onResilience => m_Resilience;
    private ReactiveProperty<double> m_Resilience = new ReactiveProperty<double>();

    /// <summary>
    /// 战时恢复力。战斗中每10秒恢复一次当前值数量的HP
    /// </summary>
    public double battleResilience { get => m_BattleResilience.Value; set => m_BattleResilience.Value = value; }
    public IObservable<double> onBattleResilience => m_BattleResilience;
    private ReactiveProperty<double> m_BattleResilience = new ReactiveProperty<double>();

    /// <summary>
    /// 生命偷取
    /// </summary>  
    public double lifeTheft { get => m_LifeTheft.Value; set => m_LifeTheft.Value = value; }
    public IObservable<double> onLifeTheft => m_LifeTheft;
    private ReactiveProperty<double> m_LifeTheft = new ReactiveProperty<double>();

    /// <summary>
    /// 伤害反击
    /// </summary>
    public double counterAttack { get => m_CounterAttack.Value; set => m_CounterAttack.Value = value; }
    public IObservable<double> onCounterAttack => m_CounterAttack;
    private ReactiveProperty<double> m_CounterAttack = new ReactiveProperty<double>();

    /// <summary>
    /// 攻击速度。影响技能的前摇后摇的时间
    /// </summary>
    public double attackSpeed { get => m_AttackSpeed.Value; set => m_AttackSpeed.Value = value; }
    public IObservable<double> onAttackSpeed => m_AttackSpeed;
    private ReactiveProperty<double> m_AttackSpeed = new ReactiveProperty<double>();

    /// <summary>
    /// 吟唱加速。减少读条所需消耗的时间
    /// </summary>
    public double chantReduction { get => m_ChantReduction.Value; set => m_ChantReduction.Value = value; }
    public IObservable<double> onChantReduction => m_ChantReduction;
    private ReactiveProperty<double> m_ChantReduction = new ReactiveProperty<double>();

    /// <summary>
    /// 冷却缩减
    /// </summary>
    public double cooldownReduction { get => m_CooldownReduction.Value; set => m_CooldownReduction.Value = value; }
    public IObservable<double> onCooldownReduction => m_CooldownReduction;
    private ReactiveProperty<double> m_CooldownReduction = new ReactiveProperty<double>();

    #endregion 功能属性

    #region 伤害加成

    /// <summary>
    /// 物理伤害加成
    /// </summary>
    public double physicalBonus { get => m_PhysicalBonus.Value; set => m_PhysicalBonus.Value = value; }
    public IObservable<double> onPhysicalBonus => m_PhysicalBonus;
    private ReactiveProperty<double> m_PhysicalBonus = new ReactiveProperty<double>();

    /// <summary>
    /// 地元素伤害加成
    /// </summary>
    public double geoBonus { get => m_GeoBonus.Value; set => m_GeoBonus.Value = value; }
    public IObservable<double> onGeoBonus => m_GeoBonus;
    private ReactiveProperty<double> m_GeoBonus = new ReactiveProperty<double>();

    /// <summary>
    /// 水元素伤害加成
    /// </summary>
    public double hydroBonus { get => m_HydroBonus.Value; set => m_HydroBonus.Value = value; }
    public IObservable<double> onHydroBonus => m_HydroBonus;
    private ReactiveProperty<double> m_HydroBonus = new ReactiveProperty<double>();

    /// <summary>
    /// 火元素伤害加成
    /// </summary>
    public double pyroBonus { get => m_PyroBonus.Value; set => m_PyroBonus.Value = value; }
    public IObservable<double> onPyroBonus => m_PyroBonus;
    private ReactiveProperty<double> m_PyroBonus = new ReactiveProperty<double>();

    /// <summary>
    /// 风元素伤害加成
    /// </summary>
    public double anemoBonus { get => m_AnemoBonus.Value; set => m_AnemoBonus.Value = value; }
    public IObservable<double> onAnemoBonus => m_AnemoBonus;
    private ReactiveProperty<double> m_AnemoBonus = new ReactiveProperty<double>();

    /// <summary>
    /// 冰元素伤害加成
    /// </summary>
    public double cyroBonus { get => m_CryoBonus.Value; set => m_CryoBonus.Value = value; }
    public IObservable<double> onCryoBonus => m_CryoBonus;
    private ReactiveProperty<double> m_CryoBonus = new ReactiveProperty<double>();

    /// <summary>
    /// 雷元素伤害加成
    /// </summary>
    public double electroBonus { get => m_ElectroBonus.Value; set => m_ElectroBonus.Value = value; }
    public IObservable<double> onElectroBonus => m_ElectroBonus;
    private ReactiveProperty<double> m_ElectroBonus = new ReactiveProperty<double>();

    /// <summary>
    /// 光元素伤害加成
    /// </summary>
    public double phoBonus { get => m_PhoBonus.Value; set => m_PhoBonus.Value = value; }
    public IObservable<double> onPhoBonus => m_PhoBonus;
    private ReactiveProperty<double> m_PhoBonus = new ReactiveProperty<double>();

    /// <summary>
    /// 暗元素伤害加成
    /// </summary>
    public double skotoBonus { get => m_skotoBonus.Value; set => m_skotoBonus.Value = value; }
    public IObservable<double> onskotoBonus => m_skotoBonus;
    private ReactiveProperty<double> m_skotoBonus = new ReactiveProperty<double>();

    #endregion 伤害加成

    #region 元素抗性

    /// <summary>
    /// 物理抗性
    /// </summary>
    public double physicalResistance { get => m_PhysicalResistance.Value; set => m_PhysicalResistance.Value = value; }
    public IObservable<double> onPhysicalResistance => m_PhysicalResistance;
    private ReactiveProperty<double> m_PhysicalResistance = new ReactiveProperty<double>();

    /// <summary>
    /// 地元素抗性
    /// </summary>
    public double geoResistance { get => m_GeoResistance.Value; set => m_GeoResistance.Value = value; }
    public IObservable<double> onGeoResistance => m_GeoResistance;
    private ReactiveProperty<double> m_GeoResistance = new ReactiveProperty<double>();

    /// <summary>
    /// 水元素抗性
    /// </summary>
    public double hydroResistance { get => m_HydroResistance.Value; set => m_HydroResistance.Value = value; }
    public IObservable<double> onHydroResistance => m_HydroResistance;
    private ReactiveProperty<double> m_HydroResistance = new ReactiveProperty<double>();

    /// <summary>
    /// 火元素抗性
    /// </summary>
    public double pyroResistance { get => m_PyroResistance.Value; set => m_PyroResistance.Value = value; }
    public IObservable<double> onPyroResistance => m_PyroResistance;
    private ReactiveProperty<double> m_PyroResistance = new ReactiveProperty<double>();

    /// <summary>
    /// 风元素抗性
    /// </summary>
    public double anemoResistance { get => m_AnemoResistance.Value; set => m_AnemoResistance.Value = value; }
    public IObservable<double> onAnemoResistance => m_AnemoResistance;
    private ReactiveProperty<double> m_AnemoResistance = new ReactiveProperty<double>();

    /// <summary>
    /// 冰元素抗性
    /// </summary>
    public double cryoResistance { get => m_CryoResistance.Value; set => m_CryoResistance.Value = value; }
    public IObservable<double> onCryoResistance => m_CryoResistance;
    private ReactiveProperty<double> m_CryoResistance = new ReactiveProperty<double>();

    /// <summary>
    /// 雷元素抗性
    /// </summary>
    public double electroResistance { get => m_ElectroResistance.Value; set => m_ElectroResistance.Value = value; }
    public IObservable<double> onElectroResistance => m_ElectroResistance;
    private ReactiveProperty<double> m_ElectroResistance = new ReactiveProperty<double>();

    /// <summary>
    /// 光元素抗性
    /// </summary>
    public double photoResistance { get => m_PhotoResistance.Value; set => m_PhotoResistance.Value = value; }
    public IObservable<double> onPhotoResistance => m_PhotoResistance;
    private ReactiveProperty<double> m_PhotoResistance = new ReactiveProperty<double>();

    /// <summary>
    /// 暗元素抗性
    /// </summary>
    public double umbroResistance { get => m_UmbroResistance.Value; set => m_UmbroResistance.Value = value; }
    public IObservable<double> onUmbroResistance => m_UmbroResistance;
    private ReactiveProperty<double> m_UmbroResistance = new ReactiveProperty<double>();

    #endregion 元素抗性

    #region 元素抗性穿刺

    /// <summary>
    /// 物理穿刺
    /// </summary>
    public double physicalPierce { get => m_PhysicalPierce.Value; set => m_PhysicalPierce.Value = value; }
    public IObservable<double> onPhysicalPierce => m_PhysicalPierce;
    private ReactiveProperty<double> m_PhysicalPierce = new ReactiveProperty<double>();

    /// <summary>
    /// 地元素穿刺
    /// </summary>
    public double geoPierce { get => m_GeoPierce.Value; set => m_GeoPierce.Value = value; }
    public IObservable<double> onGeoPierce => m_GeoPierce;
    private ReactiveProperty<double> m_GeoPierce = new ReactiveProperty<double>();

    /// <summary>
    /// 水元素穿刺
    /// </summary>
    public double hydroPierce { get => m_HydroPierce.Value; set => m_HydroPierce.Value = value; }
    public IObservable<double> onHydroPierce => m_HydroPierce;
    private ReactiveProperty<double> m_HydroPierce = new ReactiveProperty<double>();

    /// <summary>
    /// 火元素穿刺
    /// </summary>
    public double pyroPierce { get => m_PyroPierce.Value; set => m_PyroPierce.Value = value; }
    public IObservable<double> onPyroPierce => m_PyroPierce;
    private ReactiveProperty<double> m_PyroPierce = new ReactiveProperty<double>();

    /// <summary>
    /// 风元素穿刺
    /// </summary>
    public double anemoPierce { get => m_AnemoPierce.Value; set => m_AnemoPierce.Value = value; }
    public IObservable<double> onAnemoPierce => m_AnemoPierce;
    private ReactiveProperty<double> m_AnemoPierce = new ReactiveProperty<double>();

    /// <summary>
    /// 冰元素穿刺
    /// </summary>
    public double cryoPierce { get => m_CryoPierce.Value; set => m_CryoPierce.Value = value; }
    public IObservable<double> onCryoPierce => m_CryoPierce;
    private ReactiveProperty<double> m_CryoPierce = new ReactiveProperty<double>();

    /// <summary>
    /// 雷元素穿刺
    /// </summary>
    public double electroPierce { get => m_ElectroPierce.Value; set => m_ElectroPierce.Value = value; }
    public IObservable<double> onElectroPierce => m_ElectroPierce;
    private ReactiveProperty<double> m_ElectroPierce = new ReactiveProperty<double>();

    /// <summary>
    /// 光元素穿刺
    /// </summary>
    public double photoPierce { get => m_PhotoPierce.Value; set => m_PhotoPierce.Value = value; }
    public IObservable<double> onPhotoPierce => m_PhotoPierce;
    private ReactiveProperty<double> m_PhotoPierce = new ReactiveProperty<double>();

    /// <summary>
    /// 暗元素穿刺
    /// </summary>
    public double umbroPierce { get => m_UmbroPierce.Value; set => m_UmbroPierce.Value = value; }
    public IObservable<double> onUmbroPierce => m_UmbroPierce;
    private ReactiveProperty<double> m_UmbroPierce = new ReactiveProperty<double>();

    #endregion 元素抗性穿刺

}